package utils

import (
	"fmt"
	"github.com/gomodule/redigo/redis"
	"lottery/datasource"
)

// 写之前可以看看《redis 实战》 这本书， 里面的事务 和 分布式锁章节， 就会好理解这里的操作了

// 获取uid 字符串，作为 value
func getLuckyLockKey(uid int) string {
	return fmt.Sprintf("lucky_lock_%d", uid)
}

// 实现分布式锁
// 加锁操作
func LockLucky(uid int) bool {
	// 获得key
	key := getLuckyLockKey(uid)
	// 需要导入 redis 实例，
	rds := datasource.InstanceCache()
	// 设置锁： 参考文章 https://zhuanlan.zhihu.com/p/62957534
	// 参考set 命令参数设置： http://redisdoc.com/string/set.html
	// EX 设置三秒钟过期时间， NX：只在键不存在时， 才对键进行设置操作
	// 实现的就是： 带有超时限制的细粒度锁《redis 实战》一书中介绍原理。
	// 这里并没有使用 value 值进行处理。key 值就是 uid代表一个用户。细粒度锁。
	// 注意接口类型转换
	rst, _ := redis.String(rds.Do("SET", key, 1, "EX", 3, "NX"))
	if rst == "OK" { // 注意是 大写的 OK， 加不加 redis.String 转化都行，试过了
		return true
	} else {
		return false
	}
}

//解锁 : 根据不同的业务场景， 稍有不同。 《redis 实战》 中的情景例子，涉及的购买交易。
// 加锁解锁操作均 使用了 while 循环 进行进一步细化。
func UnlockLucky(uid int) bool {
	// 获取键
	key := getLuckyLockKey(uid)
	//
	rds := datasource.InstanceCache()
	rst, _ := rds.Do("DEL", key)
	if rst == 0 {
		return true
	} else {
		return false
	}
}
